package jplat.base.app.parser.impl;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import jplat.base.constant.KJPlatBase;
import jplat.base.constant.KPlatResponseCode;
import jplat.core.net.appdata.IAppDataReader;
import jplat.core.net.appdata.IDataGuard;
import jplat.core.net.appdata.encrypt.JAppRADataGuard;
import jplat.core.net.appdata.servlet.JHttpServletReader;
import jplat.core.trans.JAppConnectInfo;
import jplat.core.trans.JAppContext;
import jplat.core.trans.JClientReqHeader;
import jplat.core.trans.JClientRspHeader;
import jplat.error.exception.JSystemException;
import jplat.tools.coder.JsonCoder;
import jplat.tools.string.StringUtil;
import jplat.tools.string.XLog;

import org.apache.log4j.Logger;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

/**
 * 该类负责和App的解包和组包，以及加解密.
 * @author zhangcq
 * @date Dec 16, 2016
 * @comment
 */
public class JAppPackJsonParser extends JAppPackParser
{
	private Logger logger = Logger.getLogger(JAppPackJsonParser.class);
	
	//请求读取器
	private IAppDataReader reader = new JHttpServletReader();
	
	//数据加解密
	private IDataGuard guarder = new JAppRADataGuard();
			
	@Override
	public boolean doAppParse( JAppContext context ) throws JSystemException
	{
		// TODO Auto-generated method stub
		String json = "";
		try
		{
			//可能是密文.
			json = reader.readInputString(context, "utf-8");
			
			logger.info("__FROM_APP1:"+json);
		}
		catch (UnsupportedEncodingException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new JSystemException(KPlatResponseCode.CD_INPUT_ERROR,KPlatResponseCode.MSG_INPUT_ERROR+",t=j");
		}
		
		//没有请求数据.
		if ( StringUtil.isEmpty(json) )
		{
			return true;
		}
		
		//解析请求数据.
		doJasonParse(context,json);
		
		return false;
	}
	
	/***
	 * 解析客户端报文.
	 * @author zhangcq
	 * @date Dec 15, 2016
	 * @comment 
	 * @param context
	 * @param json
	 * @return
	 * @throws JSystemException
	 */
	public boolean doJasonParse( JAppContext context, String json ) throws JSystemException
	{
		//反序列化对象.
		JsonObject jo = new JsonParser().parse(json).getAsJsonObject();
		JsonElement header = jo.get(KJPlatBase.H_REQ_HEAD);
		JsonElement body = jo.get(KJPlatBase.H_RSP_BODY);
		if ( header == null )
		{
			logger.error(XLog.CONN_MARK+"无法获取从输入数据获得head");
			throw new JSystemException(KPlatResponseCode.CD_INPUT_ERROR,KPlatResponseCode.MSG_INPUT_ERROR+",t=hd");
		}

		//解析请求头.
		Gson gson = new Gson();
		JClientReqHeader reqHead = gson.fromJson(header,JClientReqHeader.class);
		context.setReqHeader(reqHead);
		
		context.setReqBodyByType(body,JAppContext.PACK_STATE_JSONEL);
		
		return true;
	}

	@Override
	public boolean doAppPack( JAppContext context) throws JSystemException {
		// TODO Auto-generated method stub
		return doAppJsonPack( context );
	}
	
	/**
	 * 组包
	 * @author zhangcq
	 * @date Dec 15, 2016
	 * @comment 
	 * @param context
	 * @return
	 * @throws JSystemException
	 */
	private boolean doAppJsonPack( JAppContext context ) throws JSystemException
	{
		// TODO Auto-generated method stub
		JClientRspHeader rspHeader = initRspHeader(context);		//初始化报文头.
		
		Map<String,Object> retMap = new HashMap<String,Object>();
		retMap.put(KJPlatBase.H_RSP_HEAD, rspHeader);
		retMap.put(KJPlatBase.H_RSP_BODY, context.getRspBody() );
		
		HttpServletResponse response = context.getResponse();
		BufferedOutputStream outs = null;
		try
		{
			outs = new BufferedOutputStream( context.getResponse().getOutputStream());
			
			String toApp = JsonCoder.toJsonString(retMap);
			logger.info("__TO_APP1:"+toApp);
			byte[] toData = toApp.getBytes("utf-8");
			
			//数据加密.
			JAppConnectInfo connInfo = context.getReqInfo(); 
			
			outs.write(toData);
			
			response.setContentLength(toData.length);
			response.setContentType("application/json;charset=UTF-8");
			response.setHeader(JAppConnectInfo.H_RET_HEAD, JAppConnectInfo.V_HRETCODE_SUCC);
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new JSystemException(KPlatResponseCode.CD_WRITE_ERR,KPlatResponseCode.MSG_WRITE_ERR);
		}
		finally
		{
			if ( outs != null )
			{
				try {
					outs.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		return false;
	}
}
